#!/usr/bin/evn python
# -*- coding: utf-8 -*-
"""
-------------------------------------------------
   文件名称 :     middlewares
   文件功能描述 :   功能描述
   创建人 :       小钟同学
   创建时间 :          2021/11/29
-------------------------------------------------
   修改描述-2021/11/29:         
-------------------------------------------------
"""
from grpc_interceptor import ServerInterceptor
from grpc_interceptor.exceptions import GrpcException
import abc
import grpc
from typing import Any, Callable
from grpcframe.zyxgrpc.compose_app import ComposeApp


# 扩展需要的错误处理
class ErrorBase(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def error_grpc_exc_handler(self, exception: GrpcException):
        raise NotImplementedError()


# 扩展需要的错误处理
class FinallyBase(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def finally_handler(self):
        raise NotImplementedError()


class BeforeAfterBase(metaclass=abc.ABCMeta):

    @abc.abstractmethod
    def before_handler(self, request: Any, context: grpc.ServicerContext, method_name):
        raise NotImplementedError()

    @abc.abstractmethod
    def after_handler(self, context: grpc.ServicerContext, response):
        raise NotImplementedError()


class BeforeAfterBaseNoParameter(metaclass=abc.ABCMeta):

    @abc.abstractmethod
    def before_handler(self):
        raise NotImplementedError()

    @abc.abstractmethod
    def after_handler(self):
        raise NotImplementedError()


class BaseMiddlewareNoParameter(grpc.ServerInterceptor, BeforeAfterBaseNoParameter):
    '''
    如果是基于grpc.ServerInterceptor实现的中间件，在进行中间件的循环的时候，不遵循了洋葱模型，到账可能对应的回去不到对应的信息了，
    # 它是永远的第一个去执行了！！！！！！！
    '''

    def intercept_service(self, continuation, handler_call_details):
        self.before_handler()
        resp = continuation(handler_call_details)
        self.after_handler()
        return resp


# 需要先继承ServerInterceptor再继承ABCMeta
class BaseComposeAppMiddleware(ServerInterceptor, ErrorBase, BeforeAfterBase, ComposeApp):

    def intercept(self, method: Callable, request: Any, context: grpc.ServicerContext, method_name: str, ) -> Any:
        # 创建上下文对象
        try:
            # 回调调用必要的前置的函数处理
            self.before_handler(request, context, method_name)
            response = method(request, context)
            # 调用必要的后置的函数处理
            self.after_handler(context, response)
            return response

        except GrpcException as e:
            self.error_grpc_exc_handler(e)
            # context.set_code(e.status_code)
            # context.set_details(e.details)
            raise
        finally:
            pass


# 有request, context回调处理的基础
class BaseMiddleware(ServerInterceptor, ErrorBase, BeforeAfterBase):

    def intercept(self, method: Callable, request: Any, context: grpc.ServicerContext, method_name: str, ) -> Any:
        # 创建上下文对象
        try:
            # 回调调用必要的前置的函数处理
            self.before_handler(request, context, method_name)
            response = method(request, context)
            # 调用必要的后置的函数处理
            self.after_handler(context, response)
            return response
        except GrpcException as e:
            self.error_grpc_exc_handler(e)
            # context.set_code(e.status_code)
            # context.set_details(e.details)
            raise
        finally:
            pass


# 有request, context回调处理的基础
class BaseMiddlewareGrequestcontext(ServerInterceptor, ErrorBase, BeforeAfterBaseNoParameter, FinallyBase):

    def intercept(self, method: Callable, request: Any, context: grpc.ServicerContext, method_name: str, ) -> Any:
        # 创建上下文对象
        try:
            # 回调调用必要的前置的函数处理
            self.before_handler()
            response = method(request, context)
            # 调用必要的后置的函数处理
            self.after_handler()
            return response
        except GrpcException as e:
            self.error_grpc_exc_handler(e)
            # context.set_code(e.status_code)
            # context.set_details(e.details)
            raise
        finally:
            self.finally_handler()
